package com.intelligentmeterreadingsys.httpserver;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;

/**
 * 有文件参数请求类
 * 
 * @author king
 * 
 */
public class UploadHttpClient {

    /**
     * 
     * @param url
     *            请求地址
     * @param parammap
     *            普通参数文件名
     * @param filemap
     *            文件参数
     * 
     * @return
     */
    public static String uploadSubmit(String url, Map<String, String> parammap, Map<File, String> filemap, Map<String, String> maps) {

	HttpPost post = new HttpPost(url);
	HttpClient httpclient = new DefaultHttpClient();

	MultipartEntity entity = new MultipartEntity();
	if (maps != null && !maps.isEmpty()) {
	    for (String key : maps.keySet()) {
		if (maps.get(key) != null && !maps.get(key).equals("")) {

		    try {

			entity.addPart(key, new StringBody(maps.get(key)));
		    } catch (UnsupportedEncodingException e) {

			e.printStackTrace();
		    }
		}
	    }
	}
	System.out.println("发起请求");
	if (parammap != null && !parammap.isEmpty()) {

	    for (String key : parammap.keySet()) {
		try {

		    if (key != null && !key.equals("")) {
			System.out.println("key:" + key + "value:" + parammap.get(key));
			entity.addPart(parammap.get(key), new StringBody(key));
		    }

		} catch (UnsupportedEncodingException e) {

		    e.printStackTrace();
		}
	    }
	}
	System.out.println("发起请求");
	if (filemap != null && !filemap.isEmpty()) {
	    for (File key : filemap.keySet()) {
		File file = key;
		if (file.exists()) {
		    entity.addPart(filemap.get(key), new FileBody(file, "application/octet-stream"));
		}
	    }
	}
	System.out.println("发起请求");
	StringBuffer sb = new StringBuffer();
	post.setEntity(entity);
	HttpResponse response;
	try {
	    response = httpclient.execute(post);

	    int stateCode = response.getStatusLine().getStatusCode();

	    if (stateCode == HttpStatus.SC_OK) {
		HttpEntity result = response.getEntity();
		if (result != null) {
		    InputStream is = result.getContent();
		    BufferedReader br = new BufferedReader(new InputStreamReader(is));
		    String tempLine;
		    while ((tempLine = br.readLine()) != null) {
			sb.append(tempLine);
		    }
		}
	    }
	    post.abort();
	} catch (ClientProtocolException e) {
	    e.printStackTrace();
	    return "error";
	} catch (IOException e) {

	    return "error";
	}

	return sb.toString();
    }

    /**
     * 通过拼接的方式构造请求内容，实现参数传输以及文件传输
     * 
     * @param actionUrl
     *            访问的服务器URL
     * @param params
     *            普通参数
     * @param files
     *            文件参数
     * @return
     * @throws IOException
     */
    public static String post(String actionUrl, Map<String, String> params, Map<String, File> files) throws IOException {

	String BOUNDARY = java.util.UUID.randomUUID().toString();
	String PREFIX = "--", LINEND = "\r\n";
	String MULTIPART_FROM_DATA = "multipart/form-data";
	String CHARSET = "UTF-8";

	URL uri = new URL(actionUrl);
	HttpURLConnection conn = (HttpURLConnection) uri.openConnection();
	conn.setReadTimeout(5 * 1000); // 缓存的最长时间
	conn.setDoInput(true);// 允许输入
	conn.setDoOutput(true);// 允许输出
	conn.setUseCaches(false); // 不允许使用缓存
	conn.setRequestMethod("POST");
	conn.setRequestProperty("connection", "keep-alive");
	conn.setRequestProperty("Charsert", "UTF-8");
	conn.setRequestProperty("Content-Type", MULTIPART_FROM_DATA + ";boundary=" + BOUNDARY);

	// 首先组拼文本类型的参数
	StringBuilder sb = new StringBuilder();
	for (Map.Entry<String, String> entry : params.entrySet()) {
	    sb.append(PREFIX);
	    sb.append(BOUNDARY);
	    sb.append(LINEND);
	    sb.append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + LINEND);
	    sb.append("Content-Type: text/plain; charset=" + CHARSET + LINEND);
	    sb.append("Content-Transfer-Encoding: 8bit" + LINEND);
	    sb.append(LINEND);
	    sb.append(entry.getValue());
	    sb.append(LINEND);
	}

	DataOutputStream outStream = new DataOutputStream(conn.getOutputStream());
	outStream.write(sb.toString().getBytes());
	InputStream in = null;
	// 发送文件数据
	if (files != null) {
	    for (Map.Entry<String, File> file : files.entrySet()) {
		StringBuilder sb1 = new StringBuilder();
		sb1.append(PREFIX);
		sb1.append(BOUNDARY);
		sb1.append(LINEND);
		// name是post中传参的键 filename是文件的名称
		sb1.append("Content-Disposition: form-data; name=\"file\"; filename=\"" + file.getKey() + "\"" + LINEND);
		sb1.append("Content-Type: application/octet-stream; charset=" + CHARSET + LINEND);
		sb1.append(LINEND);
		outStream.write(sb1.toString().getBytes());

		InputStream is = new FileInputStream(file.getValue());
		byte[] buffer = new byte[1024];
		int len = 0;
		while ((len = is.read(buffer)) != -1) {
		    outStream.write(buffer, 0, len);
		}

		is.close();
		outStream.write(LINEND.getBytes());
	    }

	    // 请求结束标志
	    byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINEND).getBytes();
	    outStream.write(end_data);
	    outStream.flush();
	    // 得到响应码
	    int res = conn.getResponseCode();
	    if (res == 200) {
		in = conn.getInputStream();
		int ch;
		StringBuilder sb2 = new StringBuilder();
		while ((ch = in.read()) != -1) {
		    sb2.append((char) ch);
		}
	    }
	    outStream.close();
	    conn.disconnect();
	}
	return in.toString();
    }

}
